home *** CD-ROM | disk | FTP | other *** search
- {Attached is an attempt at a Pascal RTF reader, which I abandoned in
- favor of C. The approach is to treat RTF as a language and write
- a recursive descent parser for it. The C version works quite well.
-
- The Pascal version may serve some simple purpose. It's yours to
- use freely.}
-
- program rtf;
- uses crt;
- const
- BUFSIZE = 1024;
- BEGIN_CWORD = #$DC;
- BEGIN_GROUP = #$FB;
- END_GROUP = #$FD;
- TOKENSET : set of char = [BEGIN_CWORD,BEGIN_GROUP,END_GROUP];
- var
- current_ch : char;
- current_word : string[80];
- current_parm : integer;
- rtf_version : integer;
- rtf_charset : string[8];
- default_font : integer;
- margin : integer;
- index : integer;
- buffer : array [1..BUFSIZE] of char;
- f : file;
- tagfile : text;
-
- procedure item; forward;
- procedure group; forward;
-
- function o(ch: char) : char;
- begin
- case ch of
- BEGIN_GROUP: o := '{';
- END_GROUP: o := '}';
- BEGIN_CWORD: o := '\';
- else o := ch;
- end;
- end;
-
- procedure getch;
- var
- ch : char;
- result : integer;
-
- function nextch : char;
- begin
- if index >= BUFSIZE then
- begin
- BlockRead(f, buffer, BUFSIZE, result);
-
- if result = 0 then
- begin
- writeln('Unexpected end of RTF file');
- halt;
- end;
- index := 0;
- end;
-
- inc(index);
- nextch := buffer[index];
- end;
- begin
- ch := nextch;
- case ch of
- '\':
- begin
- ch := nextch;
- if ch in ['{','}','\'] then
- current_ch := ch
- else
- begin
- current_ch := BEGIN_CWORD;
- dec(index);
- end;
- end;
- '{': current_ch := BEGIN_GROUP;
- '}': current_ch := END_GROUP;
- else current_ch := ch;
- end;
- end;
-
- procedure accept(expected: char; echo: boolean);
- begin
- if expected <> current_ch then
- begin
- writeln('SYNTAX: expected ',o(expected),' found ',o(current_ch));
- end
- else
- begin
- if echo and (current_ch in [' '..'~']+TOKENSET) then
- write(o(current_ch));
- getch;
- end;
- end;
-
- procedure accept_alpha(var alpha: string);
- begin
- alpha := '';
- while current_ch in ['A'..'Z','a'..'z'] do
- begin
- alpha := alpha + current_ch;
- accept(current_ch, TRUE);
- end;
- end;
-
- procedure accept_num(var num: integer);
- var
- value : longint;
- signed : boolean;
- begin
- if current_ch = '-' then
- begin
- signed := TRUE;
- accept('-',TRUE);
- end
- else
- signed := FALSE;
-
- value := 0;
- while current_ch in ['0'..'9'] do
- begin
- value := value*10 + ord(current_ch)-ord('0');
- accept(current_ch, TRUE);
- end;
-
- if value > 32767 then
- begin
- writeln('Integer overflow');
- value := 32767;
- end;
-
- if signed then
- num := -value
- else
- num := value;
- end;
-
- procedure control_word(var spelling: string; var parm: integer);
- begin
- accept(BEGIN_CWORD,TRUE);
- accept_alpha(spelling);
- accept_num(parm);
- if current_ch = ' ' then
- accept(' ',TRUE);
-
- writeln(tagfile, spelling:10, parm:10);
- end;
-
- procedure indent(amount: integer);
- var
- i : integer;
- begin
- inc(margin, amount);
-
- writeln;
- for i:= 1 to margin do
- write(' ');
- end;
-
- procedure content;
- begin
- indent(2);
- accept(BEGIN_GROUP,TRUE);
- indent(2);
-
- while current_ch <> END_GROUP do
- begin
- if current_ch = ';' then
- begin
- accept(current_ch, TRUE);
- indent(0);
- end
- else if current_ch = BEGIN_GROUP then
- begin
- content;
- end
- else if current_ch = BEGIN_CWORD then
- begin
- item;
- end
- else
- accept(current_ch, TRUE);
- end;
-
- indent(-2);
- accept(END_GROUP, TRUE);
- indent(-2);
- end;
-
- procedure item;
- begin
- repeat
- if current_ch = BEGIN_GROUP then
- begin
- content;
- end
- else if current_ch = ';' then
- begin
- accept(';', TRUE);
- indent(0);
- end
- else
- begin
- while not (current_ch in [BEGIN_GROUP,END_GROUP,';']) do
- accept(current_ch, TRUE);
- end;
- until not (current_ch in [BEGIN_GROUP,';',BEGIN_CWORD]);
- end;
-
- procedure content1;
- var
- alpha : string[80];
- parm : integer;
- begin
- while (current_ch <> END_GROUP) do
- begin
- case current_ch of
- BEGIN_GROUP:
- group;
- BEGIN_CWORD:
- control_word(alpha, parm);
- else
- begin
- {writeln('ERROR: unknown token: ',o(current_ch));}
- accept(current_ch, TRUE);
- end;
- end;
- end;
- end;
-
- procedure group;
- begin
- indent(2);
- accept(BEGIN_GROUP, TRUE);
- indent(2);
-
- content1;
-
- indent(-2);
- accept(END_GROUP, TRUE);
- indent(-2);
- end;
-
- procedure version;
- var
- alpha : string[80];
- begin
- control_word(alpha, rtf_version);
- if alpha <> 'rtf' then
- begin
- writeln('Not an RTF file');
- halt;
- end;
- end;
-
- procedure character_set;
- var
- parm : integer;
- begin
- control_word(rtf_charset, parm);
- end;
-
- procedure rtfile;
- begin
- accept(BEGIN_GROUP, TRUE);
- indent(2);
-
- version;
- character_set;
-
- content1;
-
- indent(-2);
- accept(END_GROUP, TRUE);
- end;
-
- begin
- ClrScr;
- margin := 0;
-
- assign(f, ParamStr(1));
- reset(f, 1);
- assign(output, '');
- rewrite(output);
- assign(tagfile, 'tagfile.dat');
- rewrite(tagfile);
-
- index := BUFSIZE;
- getch;
-
- rtfile;
- end.
-
- +-------------------------------------------------+
- | John Day
- | Computer Science Innovations,Inc
- | Principal Engineer PHONE: (407) 676-2923 ext:410
- | Melbourne, Fl FAX: (407) 676-3255
- | WWW: http://www.csihq.com
- | EMAIL: jday@csihq.com
- +--------------------------------------------------+
-